#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <vector>
#include <string>

/**
 * @brief 错误处理函数
 * @param msg 错误消息
 */
static void die(const char *msg) {
    int err = errno;
    fprintf(stderr, "[%d] %s\n", err, msg);
    abort();
}

/**
 * @brief 从缓冲区读取32位整数
 * @param buf 缓冲区
 * @return 32位整数
 */
static uint32_t read_le32(const uint8_t *buf) {
    uint32_t val = 0;
    memcpy(&val, buf, 4);
    return val;
}

/**
 * @brief 向缓冲区写入32位整数
 * @param buf 缓冲区
 * @param val 32位整数
 */
static void write_le32(uint8_t *buf, uint32_t val) {
    memcpy(buf, &val, 4);
}

/**
 * @brief 从缓冲区读取64位整数
 * @param buf 缓冲区
 * @return 64位整数
 */
static uint64_t read_le64(const uint8_t *buf) {
    uint64_t val = 0;
    memcpy(&val, buf, 8);
    return val;
}

/**
 * @brief 从缓冲区读取双精度浮点数
 * @param buf 缓冲区
 * @return 双精度浮点数
 */
static double read_dbl(const uint8_t *buf) {
    double val = 0;
    memcpy(&val, buf, 8);
    return val;
}

/**
 * @brief 序列化类型
 */
enum {
    SER_NIL = 0,    // 空值
    SER_ERR = 1,    // 错误码 + 消息
    SER_STR = 2,    // 字符串
    SER_INT = 3,    // int64
    SER_DBL = 4,    // double
    SER_ARR = 5,    // 数组
};

/**
 * @brief 发送请求
 * @param fd 套接字
 * @param cmd 命令参数
 * @return 发送成功返回0
 */
static int32_t send_req(int fd, const std::vector<std::string> &cmd) {
    uint32_t len = 4;
    for (const std::string &s : cmd) {
        len += 4 + s.size();
    }
    if (len > 4096) {
        return -1;
    }

    char wbuf[4 + 4096];
    write_le32((uint8_t *)&wbuf[0], len);
    write_le32((uint8_t *)&wbuf[4], cmd.size());
    size_t cur = 8;
    for (const std::string &s : cmd) {
        write_le32((uint8_t *)&wbuf[cur], s.size());
        memcpy(&wbuf[cur + 4], s.data(), s.size());
        cur += 4 + s.size();
    }

    uint32_t total_len = len + 4;
    return write(fd, wbuf, total_len) == (ssize_t)total_len ? 0 : -1;
}

/**
 * @brief 解析响应数据
 * @param data 响应数据
 * @param len 数据长度
 * @param pos 当前位置（引用）
 * @return 解析成功返回0
 */
static int32_t parse_response(const uint8_t *data, uint32_t len, uint32_t &pos) {
    if (pos >= len) {
        printf("(nil)\n");
        return 0;
    }
    
    uint8_t type = data[pos++];
    switch (type) {
    case SER_NIL:
        printf("(nil)");
        break;
    case SER_ERR:
        if (pos + 4 > len) return -1;
        {
            int32_t code = 0;
            memcpy(&code, &data[pos], 4);
            pos += 4;
            if (pos + 4 > len) return -1;
            uint32_t msg_len = read_le32(&data[pos]);
            pos += 4;
            if (pos + msg_len > len) return -1;
            printf("(err) %d %.*s", code, msg_len, &data[pos]);
            pos += msg_len;
        }
        break;
    case SER_STR:
        if (pos + 4 > len) return -1;
        {
            uint32_t str_len = read_le32(&data[pos]);
            pos += 4;
            if (pos + str_len > len) return -1;
            printf("\"%.*s\"", str_len, &data[pos]);
            pos += str_len;
        }
        break;
    case SER_INT:
        if (pos + 8 > len) return -1;
        {
            int64_t val = (int64_t)read_le64(&data[pos]);
            pos += 8;
            printf("(int) %lld", (long long)val);
        }
        break;
    case SER_DBL:
        if (pos + 8 > len) return -1;
        {
            double val = read_dbl(&data[pos]);
            pos += 8;
            printf("(dbl) %g", val);
        }
        break;
    case SER_ARR:
        if (pos + 4 > len) return -1;
        {
            uint32_t arr_len = read_le32(&data[pos]);
            pos += 4;
            printf("(arr) len=%u", arr_len);
            for (uint32_t i = 0; i < arr_len; ++i) {
                printf("\n  [%u] ", i);
                if (parse_response(data, len, pos) != 0) {
                    return -1;
                }
            }
        }
        break;
    default:
        printf("Unknown response type: %u", type);
        return -1;
    }
    return 0;
}

/**
 * @brief 读取响应
 * @param fd 套接字
 * @return 读取成功返回0
 */
static int32_t read_res(int fd) {
    char rbuf[4 + 4096 + 1];
    errno = 0;
    int32_t err = read(fd, rbuf, 4);
    if (err != 4) {
        if (err < 0) {
            perror("read");
        } else {
            fprintf(stderr, "EOF\n");
        }
        return -1;
    }

    uint32_t len = read_le32((uint8_t *)rbuf);
    if (len > 4096) {
        fprintf(stderr, "too long\n");
        return -1;
    }

    err = read(fd, &rbuf[4], len);
    if (err != (int32_t)len) {
        if (err < 0) {
            perror("read");
        } else {
            fprintf(stderr, "EOF\n");
        }
        return -1;
    }

    uint32_t pos = 0;
    return parse_response((uint8_t *)&rbuf[4], len, pos);
}

/**
 * @brief 执行命令并显示结果
 */
static void exec_cmd(int fd, const std::vector<std::string> &cmd) {
    printf("> ");
    for (size_t i = 0; i < cmd.size(); i++) {
        if (i > 0) printf(" ");
        printf("%s", cmd[i].c_str());
    }
    printf("\n");
    
    if (send_req(fd, cmd) != 0) {
        printf("发送失败\n");
        return;
    }
    
    printf("< ");
    if (read_res(fd) != 0) {
        printf("读取失败\n");
    }
    printf("\n\n");
}

/**
 * @brief 主函数
 */
int main() {
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd < 0) {
        die("socket()");
    }

    struct sockaddr_in addr = {};
    addr.sin_family = AF_INET;
    addr.sin_port = htons(1234);
    addr.sin_addr.s_addr = ntohl(INADDR_LOOPBACK);
    int rv = connect(fd, (const struct sockaddr *)&addr, sizeof(addr));
    if (rv) {
        die("connect");
    }

    printf("=== Redis服务器功能测试 ===\n\n");

    // 字符串操作测试
    printf("--- 字符串操作测试 ---\n");
    exec_cmd(fd, {"set", "name", "张三"});
    exec_cmd(fd, {"set", "age", "25"});
    exec_cmd(fd, {"get", "name"});
    exec_cmd(fd, {"get", "age"});
    exec_cmd(fd, {"get", "nonexistent"});

    // 键操作测试
    printf("--- 键操作测试 ---\n");
    exec_cmd(fd, {"keys"});
    exec_cmd(fd, {"del", "age"});
    exec_cmd(fd, {"keys"});

    // 有序集合测试
    printf("--- 有序集合测试 ---\n");
    exec_cmd(fd, {"zadd", "scores", "95.5", "数学"});
    exec_cmd(fd, {"zadd", "scores", "87.0", "英语"});
    exec_cmd(fd, {"zadd", "scores", "92.5", "语文"});
    exec_cmd(fd, {"zscore", "scores", "数学"});
    exec_cmd(fd, {"zquery", "scores", "0", "", "0", "10"});
    exec_cmd(fd, {"zrem", "scores", "英语"});
    exec_cmd(fd, {"zquery", "scores", "0", "", "0", "10"});

    // TTL测试
    printf("--- TTL测试 ---\n");
    exec_cmd(fd, {"set", "temp", "临时数据"});
    exec_cmd(fd, {"pexpire", "temp", "3000"});  // 3秒过期
    exec_cmd(fd, {"pttl", "temp"});
    exec_cmd(fd, {"get", "temp"});

    printf("--- 测试完成 ---\n");
    close(fd);
    return 0;
} 